postcss 是一款允許使用 JS 套件來轉換 CSS 的工具集合,例如 autoprefixer(會添加一些瀏覽器的前綴)、cssnext(可以寫一些較新的 css 語法)、postcss-modules (其實跟 css-module 差不多功用,但是做成套件),這些都是由對應的 postcss 套件去實現的,這篇裡面會整理一些常用的插件。
autoPrefixer 是 postcss 相當流行的套件之一,會自動添加 CSS 屬性兼容瀏覽器的前綴,create-react-app 中默認支持 autoPrefixer。下面的範例中 .box
經過 autoPrefixer 編譯,會將原本的 transform
添加上 -webkit
的版本,這樣就能支援 chrome 以及 safari 瀏覽器上的渲染。
.box {
transform: rotate(180deg);
}
// 經過編譯後轉為
.box {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
postcss-cssnext 讓使用者可以使用比較新的語法,例如 CSS4。這邊的範例是使用 var
變數來自定義 CSS 屬性,以方便調用,使用方式和 sass 中的變數用法很像。
// 自定義 --primaryColor
:root {
--primaryColor: #939393;
}
// 使用 var 來調用 --primaryColor
.title {
font-size: 18px;
color: var(--primaryColor);
}
//編譯後
.title {
font-size: 18px;
color: #939393;
}
cssnano 是一個壓縮 CSS 用的套件,會自動去除掉註解或是重複的 CSS 屬性。
css-in-js 實際上就是用 js 來寫 CSS 代碼,目前已經有些套件在使用,如 styled-components、emotion 等。以 styled-components 為例,它結合了 css-module、autoprefixer 的精髓,甚至還可以模組化 CSS,是目前 css-in-js 中主流的方案之一,有著以下的特點:
class
名:和 css-module 類似的方式,生成唯一的 class
名,避免汙染全域 CSS。class
來維持樣式。styled-components 跟許多 JS 套件一樣,下載安裝即可使用,安裝指令如下
yarn add styled-components
styled-components 提供了一系列的標籤函式,例如 button
, h1
, h2
, div
, p
等等,標籤函式調用時會生成相應的標籤元件,如 Button
, Div
等,並且可以賦給變數,任意命名。這其實是運用 ES6 中的標籤模板語法,函式有一種透過字串調用傳參數的方式,例如下面有一個函式,參數為 123
getPhone(123)
// 字串寫法
getPhone`123`
styled-components 基本的用法就是使用標籤函式,如其中的 styled
,裡面就有許多標籤函式,下面的範例我們調用 h1 來使用
import styled from 'styled-components';
const Title = styled.h1`
font-size: 22px;
text-align: center;
font-weight: 600;
`;
<App>
<Title>這是標籤組件,會帶入 Title 中的 h1 和 css 屬性</Title>
</App>
最終當這個 Title
組件在網頁上渲染出來會像下面的範例,有 h1
標籤,並且裡面生成一個 hash class
(不會有重複命名),同時這個 class
的屬性,就是我們上面看到的 Title
的 CSS 屬性。
<div>
<h1 class="bzvmhr">這是標籤組件,會帶入 Title 中的 h1 和 css 屬性</h1>
</div>
styled-components 也支持 sass 的巢狀寫法,如下面在 Content
元件中去定義第一層 h1
和 .description
的 CSS 屬性
import styled from 'styled-components';
const Content = styled.div`
font-size: 14px;
text-align: left;
font-weight: 400;
> h1 {
font-size: 22px;
text-align: center;
font-weight: 600;
}
> .description {
color: #939393;
}
`;
<App>
<Content>
<h1>Title</h1>
<div className="description">Description</div>
</Content>
</App>
由於 styled-components 使用的其實是 CSS 元件化的概念,因此也有 props
可以傳送參數,並且可以根據傳遞的參數去改變元件使用的 CSS 屬性
import styled, {css} from 'styled-components';
// styled.button`` 相當於 styled.button() 函式調用的方式,但是在執行完之後,會得到一個 React 元件,裡面已經包含了 css 樣式,因為是元件,所以也有 props 屬性可以傳遞參數
// props 會引用傳遞的參數,如果有該參數,就會執行後面的 css function, css function 是 styled-components 提供的一個方法
const Button = styled.button`
background-color: blue;
color: white;
${props => props.primary && css `
background-color: ;
color: ;
`}
`
// 第二個 Button 透過 props 傳遞 primary 參數,得到 primary 樣式
const App = (props) => {
return <div className="wrap">
<Button>送出</Button>
<Button primary>送出</Button>
</div>
}
若是原本已經有一個元件,在其他地方調用時想增加新的樣式或改變一些原有樣式,也可以利用 styled()
方法調用到新元件上做拓展,如下面的範例,我們在 ProductTitle
中調用 Title
元件,並更改新增 CSS 屬性
import styled from 'styled-components';
const Title = styled.h1`
font-size: 22px;
text-align: center;
font-weight: 600;
`;
const ProductTitle = styled(Title)`
font-size: 16px;
color: #33333;
`;
<App>
<Title>我是拓展前的 Title</Title>
<ProductTitle>我是拓展後的 Title</ProductTitle>
</App>
假如原本有一個普通的元件,在其他地方使用時想增加 CSS 屬性,也可以用 styled()
來調用並賦予 CSS 屬性
import styled from 'styled-components';
const Menu = () => {
return (
<ul>
<li>link1</li>
<li>link2</li>
</ul>
)
}
const PrimaryMenu = styled(Menu)`
font-size: 16px;
color: white;
background: blue;
`;
<App>
<Menu>我是拓展前的 Menu</Menu>
<Menu>我是拓展樣式後的 Menu</Menu>
</App>
這篇整理了 postcss 和 styled-components,下一篇開始會整理 React 中 class component 及 function component 的差異與使用方式。